import { shallowEqual } from '@gnlab/utils'
import { useDebounce } from '@gnlab/utils/env-react'
import { message } from 'antd'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import type { MatchedHistory, TextRecord } from '@/services/contact-chat'

const searchPageSize = 5

interface SearchState {
  conditions: {
    // 搜索条件
    keyword: string // 关键词
    wxids: string[]
    receivedTransfers: typeof services.transfers.receiveList.value
  }
  loadingInfo: {
    // 加载状态
    loading: boolean // 是否正在加载
    page: number // 已加载的页码（加载成功后才会更新，0 代表还没完成过加载）
    full: boolean // 是否已完全加载
  }
  matches: MatchedHistory[] // 当前搜索到的联系人列表
}

type SearchAction =
  // 指定搜索条件，若 keyword 不为空，会开始新的搜索
  | { type: 'set-conditions'; conditions: SearchState['conditions'] }
  // 类似 set-conditions，不过只更新 keyword
  | { type: 'set-keyword'; keyword: string }
  // 开始加载下一页
  | { type: 'next-page' }
  // 取得搜索结果（初始的或翻页的）
  | { type: 'loaded'; result: MatchedHistory[] }

function getInitialState(conditions: SearchState['conditions']): SearchState {
  const empty = conditions.keyword === ''
  return {
    conditions,
    loadingInfo: { loading: !empty, page: 0, full: empty },
    matches: [],
  }
}

function searchReducer(state: SearchState, action: SearchAction): SearchState {
  switch (action.type) {
    case 'set-conditions':
      return getInitialState(action.conditions)
    case 'set-keyword':
      return getInitialState({ ...state.conditions, keyword: action.keyword })
    case 'next-page':
      return state.loadingInfo.full
        ? state
        : { ...state, loadingInfo: { ...state.loadingInfo, loading: true } }
    case 'loaded': {
      const { result } = action
      return {
        ...state,
        loadingInfo: {
          loading: false,
          page: state.loadingInfo.page + 1,
          full: result.length < searchPageSize,
        },
        matches: [...state.matches, ...result],
      }
    }
    default:
      throw new Error()
  }
}

export function useSearch(initialKeyword: string) {
  const [wxids, receivedTransfers] = useStreams(
    services.qywxs.usableWxids,
    services.transfers.receiveList,
  )
  const [{ conditions, loadingInfo, matches }, dispatch] = useReducer(
    searchReducer,
    getInitialState({ keyword: initialKeyword, wxids, receivedTransfers }),
  )

  // 若 conditions 内容有变化，更新 state，重新进行搜索
  const newestConditions = { keyword: conditions.keyword, wxids, receivedTransfers }
  if (!shallowEqual(conditions, newestConditions))
    dispatch({ type: 'set-conditions', conditions: newestConditions })

  // 对搜索关键词的更新延迟生效
  const setKeyword = useDebounce(
    (keyword: string) => dispatch({ type: 'set-keyword', keyword }),
    500,
  )

  function nextPage() {
    if (!loadingInfo.loading && !loadingInfo.full) dispatch({ type: 'next-page' })
  }

  useEffect(() => {
    if (!loadingInfo.loading) return

    let cancelled = false
    void services.chat
      .searchHistory({
        keyword: conditions.keyword,
        wxids: conditions.wxids,
        conversationIds: [...conditions.receivedTransfers.values()].map(v => v.conversationId),
        page: loadingInfo.page + 1,
        pageSize: searchPageSize,
      })
      .then(res => {
        if (cancelled) return
        if (res.success) {
          dispatch({ type: 'loaded', result: res.data })
        } else {
          void message.warning('历史记录搜索失败：' + res.error)
          dispatch({ type: 'loaded', result: [] })
        }
      })
    return () => {
      cancelled = true
    }
  }, [conditions, loadingInfo])

  return {
    keyword: conditions.keyword,
    setKeyword,
    loading: loadingInfo.loading,
    full: loadingInfo.full,
    nextPage,
    matches,
  }
}

export interface Focusing {
  match: MatchedHistory
  record: TextRecord
}
